package cn.edu.lingnan.service.impl;

import cn.edu.lingnan.domain.dto.DepositDto;
import cn.edu.lingnan.domain.dto.WthdrawDto;
import cn.edu.lingnan.domain.pojo.*;
import cn.edu.lingnan.domain.vo.Card_UserVo;
import cn.edu.lingnan.domain.vo.CardsVo;
import cn.edu.lingnan.domain.vo.UserVo;
import cn.edu.lingnan.mapper.AtmMapper;
import cn.edu.lingnan.service.AtmService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;

import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class AtmServiceImpl  implements AtmService {
    private static final Logger log = LoggerFactory.getLogger(AtmServiceImpl.class);
    private final AtmMapper atmMapper;

    @Override
    public List<Atm> getAtmInfo() {
        return  atmMapper.getAtmInfo();
    }

    @Override
    public Atm getAtmInfoByAid(Integer id) {
        return  atmMapper.getAtmInfoByAid(id);
    }

    @Override
    public UserVo inputUserInfo(String name, String password) {
        UserVo userVo =   atmMapper.inputUserInfo(name, password);
        List<Accounts> accountsList;
        if(userVo!=null){
            //获取用户的账户信息
            accountsList =  atmMapper.getAtmInfoByUser(userVo.getUserId());
            userVo.setAccountList(accountsList);
            return userVo;
        }
        return  null;
    }

    @Override
    public List<CardsVo> getCashExchangeCard() {
        return  atmMapper.getCashExchangeCard();
    }

    @Override
    public Card_UserVo verifyBankCardPassword(String cardNumber, String cardPassword) {
        Cards cards = atmMapper.verifyBankCardPassword(cardNumber, cardPassword);
        log.info("verifyBankCardPassword: " + cards);
        if (cards == null) {
            return null;
        }

        // 获取用户信息
        UserVo userVo = atmMapper.getUsersByCardId(cards.getOwnerId());
        List<Accounts> accountsList = new ArrayList<>();

        // 手动解析 accounts 字段
        List<Integer> accountIds;
        try {
            ObjectMapper mapper = new ObjectMapper();
            accountIds = mapper.readValue(cards.getAccounts(), new TypeReference<List<Integer>>() {});
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to parse accounts JSON", e);
        }

        // 查询账户信息
        for (Integer accountId : accountIds) {
            Accounts accounts = atmMapper.getAccountInfoById(accountId);
            accountsList.add(accounts);
        }

        // 构建返回对象
        Card_UserVo cardUserVo = Card_UserVo.builder()
                .cardNumber(cards.getCardNumber())
                .branchCode(cards.getBranchCode())
                .bank(cards.getBank())
                .userId(userVo.getUserId())
                .name(userVo.getName())
                .address(userVo.getAddress())
                .phoneNumber(userVo.getPhoneNumber())
                .accountList(accountsList)
                .build();

        return cardUserVo;
    }

    @Override
    @Transactional
    public String withdraw(WthdrawDto wthdrawDto) {
        //先查询余额是否足够
        Integer balance = atmMapper.getBalanceByAccountId(wthdrawDto.getAccountId());
        if(balance<wthdrawDto.getBalance()){
            return "余额不足";
        }
        // 执行取款操作
        atmMapper.withdraw(wthdrawDto);

        // 记录日志
        Logs logs = new Logs();
        logs.setOperationType("取款");
        logs.setDetails("用户ID为：" + wthdrawDto.getUserId() + "，用户名为：" +
                wthdrawDto.getUserName() + "，取款金额为：" + wthdrawDto.getBalance() +
                "，取款账户为：" + wthdrawDto.getAccountId());
        atmMapper.insertWithdrawLog(logs); // 修复：插入日志时传递 Logs 对象

        // 记录账单
        Receipts receipts = new Receipts();
        receipts.setAccountId(wthdrawDto.getAccountId());
        receipts.setBalance(wthdrawDto.getBalance());
        receipts.setOperationType("取款");
        receipts.setContent("用户ID为：" + wthdrawDto.getUserId() + "，用户名为：" +
                wthdrawDto.getUserName() + "，取款金额为：" + wthdrawDto.getBalance() +
                "，取款账户为：" + wthdrawDto.getAccountId());

        // 获取当前时间并格式化
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        receipts.setCreateTime(now.format(formatter)); // 设置创建时间

        atmMapper.insertReceipt(receipts); // 保存账单信息

        // 返回操作成功信息
        return "取款操作成功，金额：" + wthdrawDto.getBalance();
    }

    @Override
    public Accounts getAccountInfoById(Integer accountId) {
        return  atmMapper.getAccountInfoById(accountId);
    }

    @Override
    public String deposit(DepositDto depositDto) {
        // 执行存款操作
        atmMapper.deposit(depositDto);


        // 记录日志
        Logs logs = new Logs();
        logs.setOperationType(" 存款");
        logs.setDetails("用户ID为：" +  depositDto.getUserId() + "，用户名为：" +
                depositDto.getUserName() + "， 存款金额为：" +  depositDto.getBalance() +
                "， 存款账户为账户为：" +  depositDto.getAccountId());
        atmMapper.insertWithdrawLog(logs); // 修复：插入日志时传递 Logs 对象

        // 记录账单
        Receipts receipts = new Receipts();
        receipts.setAccountId( depositDto.getAccountId());
        receipts.setBalance( depositDto.getBalance());
        receipts.setOperationType(" 存款");
        receipts.setContent("用户ID为：" +   depositDto.getUserId() + "，用户名为：" +
                depositDto.getUserName() + "， 存款金额为：" +  depositDto.getBalance() +
                "， 存款账户为：" +  depositDto.getAccountId());

        // 获取当前时间并格式化
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        receipts.setCreateTime(now.format(formatter)); // 设置创建时间

        atmMapper.insertReceipt(receipts); // 保存账单信息

        // 返回操作成功信息
        return "存款操作成功，金额：" +  depositDto.getBalance();
    }

    @Override
    public String exportExcel(Integer accountId, HttpServletResponse response)  throws IOException {
        //查询账单信息
        List<Receipts> receiptsList = atmMapper.getReceiptsByAccountId(accountId);
        // 创建一个新的工作簿
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("账单信息");

        // 创建标题行并居中显示
        Row titleRow = sheet.createRow(0);
        Cell titleCell = titleRow.createCell(0);
        titleCell.setCellValue(" 账单信息记录");
        CellStyle titleStyle = createBoldAndCenterCellStyle(workbook);
        titleCell.setCellStyle(titleStyle);
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 8)); // 合并单元格用于标题

        // 创建显示用户名的行
        Row userRow = sheet.createRow(1);
        Cell userCell = userRow.createCell(0);
        userCell.setCellValue("用户: " +  "张三");
        userCell.setCellStyle(createBoldCellStyle(workbook));
        sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 8)); // 合并单元格用于用户名

        // 添加导出时间
        Row exportTimeRow = sheet.createRow(2);
        Cell exportTimeCell = exportTimeRow.createCell(0);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        exportTimeCell.setCellValue("导出时间: " + formatter.format(System.currentTimeMillis()));
        exportTimeCell.setCellStyle(createBoldCellStyle(workbook));
        sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 8)); // 合并单元格用于导出时间

        // 创建表头行并居中显示
        Row headerRow = sheet.createRow(3);
        String[] headers = {"记录ID", "账户ID", "操作类型", "操作金额", "单位", "操作时间", "操作内容"};
        CellStyle headerStyle = createBoldAndCenterCellStyle(workbook);
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }

        // 填充数据行并居中显示
        CellStyle contentStyle = createCenterCellStyle(workbook);
        int rowIndex = 4;
        for (Receipts record : receiptsList) {
            Row row = sheet.createRow(rowIndex++);
            row.createCell(0).setCellValue(record.getReceiptId());
            row.createCell(1).setCellValue(record.getAccountId());
            row.createCell(2).setCellValue(record.getOperationType());
            row.createCell(3).setCellValue(record.getBalance());
            row.createCell(4).setCellValue("元人民币");
            row.createCell(5).setCellValue(record.getCreateTime());
            row.createCell(6).setCellValue(record.getContent());

            // Ensure each cell is created and style is applied
            for (int i = 0; i <= 6; i++) {
                if (row.getCell(i) == null) {
                    row.createCell(i);
                }
                row.getCell(i).setCellStyle(contentStyle);
            }
        }

        // 设置响应类型以便下载
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment;filename=carbon_records.xlsx");

        // 将工作簿写入输出流
        workbook.write(response.getOutputStream());
        workbook.close();

        return "";
    }
    // 创建加粗并居中样式的方法
    private CellStyle createBoldAndCenterCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);
        return style;
    }

    // 创建加粗样式的方法
    private CellStyle createBoldCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);
        return style;
    }

    // 创建居中样式的方法
    private CellStyle createCenterCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        return style;
    }

}
